
package com.rt.schedulenew.utils.aop;
import com.google.common.cache.CacheLoader;
import java.util.concurrent.TimeUnit;
import com.google.common.cache.CacheBuilder;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.annotation.Around;
import java.lang.reflect.Method;
import com.rt.schedulenew.utils.global.BusinessException;
import com.rt.schedulenew.utils.annotation.ServiceLimit;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.lang.ProceedingJoinPoint;
import com.google.common.util.concurrent.RateLimiter;
import com.google.common.cache.LoadingCache;
import org.slf4j.Logger;
import org.springframework.core.annotation.Order;
import org.springframework.context.annotation.Configuration;
import org.aspectj.lang.annotation.Aspect;
@Aspect
@Configuration
@Order(1)
public class LimitAspect
{
    private Logger log = LoggerFactory.getLogger(LimitAspect.class);
    private static LoadingCache<String, RateLimiter> caches;
    
    @Around("execution(public * *(..))  && @annotation(com.rt.schedulenew.utils.annotation.ServiceLimit)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Method method = signature.getMethod();
        ServiceLimit limitAnnotation = method.getAnnotation(ServiceLimit.class);
        ServiceLimit.LimitType limitType = limitAnnotation.limitType();
        String key = limitAnnotation.key();
        if (limitType.equals(ServiceLimit.LimitType.URL)) {
            key = joinPoint.getSignature().getName();
        }
        RateLimiter rateLimiter = LimitAspect.caches.get(key);
        Boolean bool = rateLimiter.tryAcquire();
        if (!bool) {
            throw new BusinessException("系统繁忙，请稍后再试");
        }
        return joinPoint.proceed();
    }
    
    static {
        LimitAspect.caches = (LoadingCache<String, RateLimiter>)CacheBuilder.newBuilder().maximumSize(1000L).expireAfterWrite(1L, TimeUnit.DAYS).build((CacheLoader)new CacheLoader<String, RateLimiter>() {
            public RateLimiter load(String key) {
                return RateLimiter.create(100.0);
            }
        });
    }
}
